package com.shycloud.mido.member.service.impl;

import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.shycloud.mido.common.core.constant.CommonConstants;
import com.shycloud.mido.common.core.exception.BusinessException;
import com.shycloud.mido.common.core.util.R;
import com.shycloud.mido.common.security.util.SecurityUtils;
import com.shycloud.mido.common.util.DateUtil;
import com.shycloud.mido.member.api.entity.*;
import com.shycloud.mido.member.api.feign.MasterFeignService;
import com.shycloud.mido.member.api.vo.AtvAttendDetailVO;
import com.shycloud.mido.member.mapper.*;
import com.shycloud.mido.member.service.AtvAttendDetailService;
import com.shycloud.mido.member.service.MemberServiceV2;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;

import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDateTime;
import java.time.ZoneId;
import java.time.temporal.ChronoUnit;
import java.util.Date;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;

@Service
@AllArgsConstructor
@Slf4j
public class AtvAttendDetailServiceImpl extends
		ServiceImpl<AtvAttendDetailMapper, AtvAttendDetail> implements AtvAttendDetailService {

	private static Log logger = LogFactory.getLog(AtvAttendDetailServiceImpl.class);

	/** 用户模块 service */
	private MemberServiceV2 memberService;
	/** 纠错大师开通硬件 feign */
	private MasterFeignService masterFeignService;

	/** 用户模块 mapper */
	private MemberMapper memberMapper;
	/** 学生活动信息 mapper */
	private AtvAttendDetailMapper atvAttendDetailMapper;
	/** 活动主表 service */
	private AtvMainActiveMapper mainMapper;
	/** 活动类型模块 mapper */
	private AtvPlaysSimpleDateMapper playsSimpleDateMapper;
	/** 硬件模块 mapper */
	private MemberActivateMapper memberActivateMapper;
	/** 会员模块 mapper */
	private MemberRoleMapper memberRoleMapper;

	@Override
	@Transactional(rollbackFor = Exception.class, timeout = 36000)
	public String signUp(String mainActiveId, String username, String showname, String headerUrl) {

		//查询此账号是否是已注册账号
		List<Member> members = memberMapper.selectList(new QueryWrapper<Member>()
				.eq("username", username)
				.eq("lock_flag", "0")
				.eq("del_flag", "0"));

		Member member = null;

		if (members.size() > 0) {
			//修改昵称
			for (Member memberUpd : members) {
				memberUpd.setShowname(showname);
				memberMapper.updateById(memberUpd);
			}
			member = members.get(0);
		}

		//新注册用户
		else {

			R registerRes = memberService.register(username, "123456", showname);
			if (registerRes.getCode() != CommonConstants.SUCCESS) {
				throw new BusinessException(registerRes.getMsg());
			}

			//查询此账号
			List<Member> memberAfter = memberMapper.selectList(new QueryWrapper<Member>()
					.eq("username", username)
					.eq("lock_flag", "0")
					.eq("del_flag", "0"));

			if (memberAfter.size() == 0) {
				logger.error(username + "--- 此账号新注册用户没找到");
				throw new BusinessException("报名失败，请稍后再试");
			} else {
				//更新头像
				member = memberAfter.get(0);
				member.setAvatar(headerUrl);
				memberService.updateById(member);
			}
		}
		//查询100天内的活动
//		LocalDateTime minusDays = LocalDateTime.now().minusDays(100);
//		Date minusDaysDate = Date.from(minusDays.atZone( ZoneId.systemDefault()).toInstant());
		//优化.gt(AtvAttendDetail::getCreateTime, minusDaysDate)
		//判断是否已经报名
		List<AtvAttendDetail> atvAttendDetails = atvAttendDetailMapper
				.selectList(new QueryWrapper<AtvAttendDetail>()
						.eq(AtvAttendDetail.COL_MEMBER_ID, member.getId()));

		if (CollectionUtils.isNotEmpty(atvAttendDetails)) {
			Date now = new Date();
			List<String> mainIds = atvAttendDetails.stream().map(AtvAttendDetail::getMainActiveId)
					.collect(Collectors.toList());
			LambdaQueryWrapper<AtvMainActive> query = Wrappers.<AtvMainActive>lambdaQuery()
					.in(AtvMainActive::getId, mainIds).eq(AtvMainActive::getDelFlag, "0");
			List<AtvMainActive> mainLists = mainMapper.selectList(query);
			for (AtvMainActive atvMainActive : mainLists) {
				//如果已经参加的活动 没开始或者没结束
				if (null == atvMainActive.getBeginDatetime() || null == atvMainActive
						.getEndDatetime() || now.getTime() <= atvMainActive.getEndDatetime()
						.getTime()) {
					throw new BusinessException("该用户有活动在报名或者进行中无法重复报名,请联系老师处理");
				}
			}
		}

		//添加报名信息表
		AtvAttendDetail atvAttendDetail = new AtvAttendDetail();
		//报名时间
		atvAttendDetail.setAttendDatetime(new Date());
		//创建时间
		atvAttendDetail.setCreateTime(new Date());
		//创建人
		atvAttendDetail.setCreateUser(member.getId());
		//有效数据
		atvAttendDetail.setDelFlag(CommonConstants.STATUS_NORMAL);
		//琴童姓名
		atvAttendDetail.setInputMemberName(showname);
		//琴童手机号 登录账号
		atvAttendDetail.setInputPhone(username);
		//关联活动ID
		atvAttendDetail.setMainActiveId(mainActiveId);
		//琴童 memberId
		atvAttendDetail.setMemberId(member.getId());
		//状态 0-已报名
		atvAttendDetail.setStatus("0");
		atvAttendDetailMapper.insert(atvAttendDetail);

		//2021-06-28 追加:返回发起者机构的电话号,默认总部电话号
		String phone = mainMapper.getActBossPhone(mainActiveId);

		return StringUtils.isEmpty(phone) ? "" : phone;
	}

	@Override
	@Transactional(rollbackFor = Exception.class, timeout = 36000)
	public boolean beginAtv(String mainActiveId) {
		//记录活动开始时间
		AtvMainActive atvMainActive = mainMapper.selectById(mainActiveId);

		if (atvMainActive == null) {
			throw new BusinessException("未查询到相关活动");
		}

		//筛选出【已签到】的用户
		List<AtvAttendDetail> atvAttendDetails = atvAttendDetailMapper
				.selectList(new QueryWrapper<AtvAttendDetail>()
						.eq(AtvAttendDetail.COL_MAIN_ACTIVE_ID, mainActiveId)
						.eq(AtvAttendDetail.COL_STATUS, "1"));

		for (AtvAttendDetail atvAttendDetail : atvAttendDetails) {
			//更新状态为【活动进行中】
			atvAttendDetail.setStatus("2");
			atvAttendDetail.setUpdateTime(new Date());
			atvAttendDetail.setUpdateUser(SecurityUtils.getMember().getId());
			atvAttendDetailMapper.updateById(atvAttendDetail);

			AtvMainActive mainActive = mainMapper.selectById(mainActiveId);
			String playId = mainActive.getPlayId();
			AtvPlaysSimpleDate type = playsSimpleDateMapper.selectById(playId);
			memberService.addVipMemberByMemberId(atvAttendDetail.getMemberId(), type.getParams() + 1);
			masterFeignService.activateByDuration(atvAttendDetail.getMemberId(), type.getParams() + 1);
		}

		AtvPlaysSimpleDate atvPlaysSimpleDate = playsSimpleDateMapper
				.selectById(atvMainActive.getPlayId());

		//计算活动开始时间 - 次日
		LocalDateTime startDate = DateUtil.toLocalDateTime(DateUtil.toZero(new Date())).plusDays(1);
		//计算活动结束时间
		int duration = atvPlaysSimpleDate.getParams();
		LocalDateTime endDate = startDate.plusDays(duration).minusSeconds(1);

		//活动开始时间
		atvMainActive
				.setBeginDatetime(Date.from(startDate.atZone(ZoneId.systemDefault()).toInstant()));
		//活动结束时间
		atvMainActive.setEndDatetime(Date.from(endDate.atZone(ZoneId.systemDefault()).toInstant()));
		//报名截止时间
		atvMainActive.setSignupEndDatetime(atvMainActive.getEndDatetime());
		return mainMapper.updateById(atvMainActive) == 1;

	}

	@Override
	public IPage<AtvAttendDetailVO> getSignUpList(Page page, String mainActiveId) {
		return atvAttendDetailMapper.getSignUpList(page, mainActiveId);
	}

	@Transactional(rollbackFor = Exception.class)
	@Override
	public void dropOut(String mainActiveId, String teatcherMemberId, String memberId) {
		LambdaQueryWrapper<AtvAttendDetail> deleteWrapper = Wrappers.<AtvAttendDetail>lambdaQuery()
				.eq(AtvAttendDetail::getMainActiveId, mainActiveId)
				.eq(AtvAttendDetail::getMemberId, memberId);

		AtvAttendDetail atvAttendDetail = atvAttendDetailMapper.selectOne(deleteWrapper);
		if (Objects.nonNull(atvAttendDetail)) {
			log.info("老师:" + teatcherMemberId + "删除用户报名：" + JSON.toJSONString(atvAttendDetail));
			atvAttendDetailMapper.delete(deleteWrapper);
		}
		//扣除VIP和硬件权限
		if ("2".equals(atvAttendDetail.getStatus())) {

			//根据udid查询套餐，获取曾经对应的 VIP 时长，将其扣除
			List<MemberActivateEntity> memberActivateEntities = memberActivateMapper
					.selectList(new QueryWrapper<MemberActivateEntity>()
							.eq("member_id", memberId)
							.eq("status", "1"));

			if (memberActivateEntities.size() != 1) {
				//在判断是否有体验设备
				memberActivateEntities = memberActivateMapper
						.selectList(new QueryWrapper<MemberActivateEntity>()
								.eq("member_id", memberId)
								.eq("status", "4"));
				if (memberActivateEntities.size() != 1) {
					throw new BusinessException(
							"对应硬件开通记录存在异常，无法执行中止操作 ~ 数量：" + memberActivateEntities.size());
				}
			}

			MemberActivateEntity activateEntity = memberActivateEntities.get(0);

			Integer durationTypeValue = activateEntity.getDuration();

			//激活开始时间
			LocalDateTime startTime = activateEntity.getStartTime();
			//中止时间
			LocalDateTime nowTime = LocalDateTime.now();
			//计算扣除时间
			Long duration = ChronoUnit.DAYS.between(startTime, nowTime) < 1 ? 1
					: ChronoUnit.DAYS.between(startTime, nowTime);
			activateEntity.setDuration(duration.intValue());
			//设置成未激活
			activateEntity.setStatus("0");
			//更新
			memberActivateMapper.updateById(activateEntity);

			//查询会员信息
			MemberRole memberRole = memberRoleMapper.selectOne(new QueryWrapper<MemberRole>()
					.eq("member_id", memberId)
					.eq("role_code", "VIP_MEMBER"));

			if (memberRole != null) {
				//执行扣除VIP操作
				//获取到期时间
				LocalDateTime endTime = memberRole.getEndTime();
				//没到期
				if (LocalDateTime.now().isBefore(endTime)) {
					LocalDateTime endTimeNew = endTime.minusDays(durationTypeValue - duration);
					memberRole.setEndTime(endTimeNew);
					memberRoleMapper.updateById(memberRole);
				}
			}

		}

	}

	@Override
	public String getIsTeacherInAct(String id, String teacherId) {
		return atvAttendDetailMapper.getIsTeacherInAct(id, teacherId) > 0 ? "1" : "0";
	}
}

